package com.afdor.rws.event.driven.support;

import com.afdor.rws.annotation.extension.Extension;
import com.afdor.rws.event.driven.EventSource;
import com.afdor.rws.event.driven.EventSourceManager;
import com.afdor.rws.event.driven.config.EventSourceConfig;
import lombok.NonNull;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 默认事件源管理器实现
 *
 * @author 悭梵
 * @date Created in 2018-08-14 18:34
 */
@Extension(value = "default", order = Extension.NORMAL_ORDER - 100, interfaceClass = EventSourceManager.class)
public class DefaultEventSourceManager implements EventSourceManager {

    /**
     * 是否已初始化
     */
    private volatile boolean init = Boolean.FALSE;

    /**
     * 配置信息
     */
    private EventSourceConfig config;

    /**
     * 事件源管理器
     */
    private ConcurrentMap<String, EventSource> eventSourceMap = new ConcurrentHashMap<String, EventSource>();

    @Override
    public <T extends EventSourceManager> T addEventSource(@NonNull EventSource eventSource) {
        if (eventSourceMap.containsKey(eventSource.getEventSourceName())) {
            throw new IllegalStateException("事件源" + eventSource.getEventSourceName() + "已存在，不能重复添加。");
        }
        eventSourceMap.putIfAbsent(eventSource.getEventSourceName(), eventSource);
        return (T) this;
    }

    /**
     * 移除指定事件源配置信息
     *
     * @param eventSourceName
     */
    public EventSourceManager remove(@NonNull String eventSourceName) {
        eventSourceMap.remove(eventSourceName);
        return this;
    }

    @Override
    public <T extends EventSource> T getEventSource(@NonNull String eventSourceName) {
        return (T) eventSourceMap.get(eventSourceName);
    }

    @Override
    public EventSourceManager init() {
        init = Boolean.TRUE;
        eventSourceMap.values().parallelStream().forEach(eventSource -> eventSource.getChannelProvider().init());
        return this;
    }

    @Override
    public void destroy() {
        init = Boolean.FALSE;
        eventSourceMap.values().parallelStream().forEach(eventSource -> eventSource.getChannelProvider().destroy());
    }

    @Override
    public <C extends EventSourceConfig> C getConfig() {
        return (C) this.config;
    }

    @Override
    public <T extends EventSourceManager, C extends EventSourceConfig> T setConfig(C config) {
        this.config = config;
        return (T) this;
    }
}
